<?php

namespace Rexzy\Http;

class Request {
    
    static private $_instance;
    private $_method;
    private $_headers = array();
    private $_put = array();
    private $_allinput = array();
    
    private function __construct() {
        $this->_method = $_SERVER['REQUEST_METHOD'];
        $this->_parseHeaders();
        parse_str( file_get_contents( 'php://input' ), $this->_put );
        $inputMethod = array( $_COOKIE, $_GET, $this->_put, $_POST );
        foreach ( $inputMethod as $methodNum => $method ) {
            foreach ( $method as $key => $value ) {
                $this->_allInput[$key] = $value;
            }
        }
    }
    
    private function _parseHeaders() {
        $header = & $this->_headers;
        // 这是apache特有的函数，可以很方便取到数据
        if (function_exists('getallheaders')) {
            $header = getallheaders();
        }
        // 其它服务器，在$_SERVER里取，有点麻烦
        // 我用$_SERVER来得到所有http请求头
        // 参考了http://www.oschina.net/question/54100_38761
        else {
            foreach ($_SERVER as $key => $value) {
                if ('HTTP_' === substr($key, 0, 5)) {
                    $header[substr($key, 5)] = $value;
                }
            }
        }
        $_header = array();
        // 格式化参数
        foreach ($header as $key => $value) {
            $key = strtoupper(str_replace('-', '_', $key));
            $_header[$key] = $value;
        }
        $header = $_header;
        if (isset($_SERVER['CONTENT_LENGTH'])) {
            $header['CONTENT_LENGTH'] = $_SERVER['CONTENT_LENGTH'];
        }
        if (isset($_SERVER['CONTENT_TYPE'])) {
            $header['CONTENT_TYPE'] = $_SERVER['CONTENT_TYPE'];
        }
        // HTTP认证信息
        if (isset($_SERVER['PHP_AUTH_DIGEST'])) {
            $header['PHP_AUTH_DIGEST'] = $_SERVER['PHP_AUTH_DIGEST'];
        } elseif (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
            $header['PHP_AUTH_USER'] = $_SERVER['PHP_AUTH_USER'];
            $header['PHP_AUTH_PW'] = $_SERVER['PHP_AUTH_PW'];
        }
        // 认证方法
        if (isset($header['AUTHORIZATION'])) {
            $match = array();
            if (preg_match('/^\w+/', $header['AUTHORIZATION'], $match)) {
                $header['AUTH_TYPE'] = $match[0];
            }
        }
    }
    
    /**
     * 获取 Request单例
     * 
     * @return object 
     */
    static public function getInstance() {
        if ( ! self::$_instance ) {
            self::$_instance = new self();
        }
        return self::$_instance; 
    }
    
    /**
     * 获取某个 Http请求头信息
     * 
     * @param string $key 请求头键值名
     * @return string 
     */
    public function header( $key ) {
        if ( $this->_headers[ $key ] ) {
            return $this->_headers[ $key ];
        }
    }
    
    /**
     * 获取全部 Http 请求头信息
     * 
     * @return string 
     */
    public function headers() {
        return $this->_headers;
    }
    
    /**
     * 判断 Http请求方法是否为 POST
     * 
     * @return bool
     */
    public function isPost() {
        return ( $this->_method === 'POST' );
    }
    
    /**
     * 判断 Http请求方法是否为 GET
     * 
     * @return bool
     */
    public function isGet() {
        return ( $this->_method === 'GET' );
    }
    
    /**
     * 判断 http 请求方法是否为 PUT
     * 
     * @return bool
     */
    public function isPut() {
        return ( $this->_method === 'PUT' ); 
    }
    
    /**
     * 判断 http 请求方法是否为 DELETE
     * 
     * @return bool
     */
    public function isDelete() {
        return ( $this->_method === 'DELETE' );
    }
    
    /**
     * 获取http请求方法
     * 
     * @return string
     */
    public function method() {
        return $this->_method;
    }
    
    /**
     * 查询 http 请求某个输入值
     * @param string $key 查询的请求输入值的键名
     * @param string $mode 查询的请求输入值的输入方法的类形
     *  'p': 为 POST 方法输入值
     *  'g': 为 GET 方法输入值
     *  'u': 为 PUT 方法输入值
     *  'c': 为 COOKIE 值
     * 
     * @return string
     */
    public function input( $key, $mode = 'p' ) {
        if( $mode == 'p' ) {
            if ( isset( $_POST[ $key ] ) ) {
                return $_POST[$key];
            }
                
        } else if ( $mode == 'g' ) {
            if ( isset( $_GET[ $key ] ) ) {
                return $_GET[ $key ];
            } else {
                return false;
            }
                
        } else if ( $mode == 'u' ) {
            if ( isset( $this->_put[ $key ] ) ) {
                return $this->_put[ $key ];
            }
                
        } else if( $mode == 'c' ) {
            if ( isset( $_COOKIE[ $key ] ) ) {
                return $_COOKIE[$key];
            }
        }
    }
    
    /**
     * 获取 http 请求全部输入值
     * @param string $mode 获取输入值的类形
     *  'a': 为获取全部输入值，包括 post、get、put和 cookie
     *  'u': 为获取 put 的全部输入值
     *  'p': 为获取 post 的全部输入值
     *  'g': 为获取 get 的全部输入值
     *  'c': 为获取 cookie 的全部输入值
     * 
     * @return array
     */
    public function allInput( $mode ) {
        if ( $mode == 'a' ) {
            return $this->_allInput;
            
        } else if ( $mode == 'p' ) { 
            return $_POST;
            
        } else if ( $mode == 'u' ) { 
            return $this->_put;
            
        } else if ( $mode == 'g' ) {
            return $_GET;
            
        } else if ( $mode == 'c' ) {
            return $_COOKIE;
        }
    }
    
      /**
     * 获取客户端IP
     * 
     * 这个方法来源于互联网
     * 
     * @return string
     */
    public function ip() {
        $ip = $_SERVER['REMOTE_ADDR'];
		if( isset( $_SERVER['HTTP_CLIENT_IP'] )
                && preg_match( '/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'] ) ) {
			$ip = $_SERVER['HTTP_CLIENT_IP'];
		} elseif( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) &&
            preg_match_all( '#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches ) ) {
			foreach ( $matches[0] as $xip ) {
				if( ! preg_match( '#^(10|172\.16|192\.168)\.#', $xip ) ) {
					$ip = $xip;
					break;
				}
			}
		}
		return $ip;
    }

}